package edison.jcr;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.sql.Date;
import java.util.Calendar;

import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.ValueFormatException;

public class ValueFactoryImpl implements ValueFactory {

	public Value createValue(String value, int type) throws ValueFormatException {
		validate(value, type);
		return new ValueImpl(value, type);
	}

	private void validate(String value, int type) throws ValueFormatException {
		try {
			switch (type) {
			case PropertyType.LONG:
				Long.valueOf(value);
				break;
			case PropertyType.DATE:
				Date.valueOf(value);
				break;
			case PropertyType.DECIMAL:
				new BigDecimal(value);
				break;
			case PropertyType.DOUBLE:
				Double.valueOf(value);
				break;
			default:
				break;
			}
		} catch (Exception e) {
			throw new ValueFormatException(e);
		}

	}

	public Value createValue(String value) {
		return new ValueImpl(value, PropertyType.STRING);
	}

	public Value createValue(long value) {
		return new ValueImpl(Long.toString(value, Character.MAX_RADIX), PropertyType.LONG);
	}

	public Value createValue(double value) {
		return new ValueImpl(Double.toString(value), PropertyType.DOUBLE);
	}

	public Value createValue(BigDecimal value) {
		return new ValueImpl(value.toString(), PropertyType.DECIMAL);
	}

	public Value createValue(boolean value) {
		return new ValueImpl(Boolean.toString(value), PropertyType.BOOLEAN);
	}

	public Value createValue(Calendar value) {
		return new ValueImpl(Long.toString(value.getTimeInMillis()), PropertyType.DATE);
	}

	public Value createValue(InputStream value) {
		Binary binary = null;
		try {
			binary = createBinary(value);
		} catch (RepositoryException e) {
			e.printStackTrace();
		}

		if (binary == null)
			return null;
		return createValue(binary);
	}

	public Value createValue(Binary value) {
		return new ValueImpl(value.toString(), PropertyType.BINARY);
	}

	public Value createValue(Node value) throws RepositoryException {
		return createValue(value, false);
	}

	public Value createValue(Node value, boolean weak) throws RepositoryException {
		String id = value.getIdentifier();
		return new ValueImpl(id, weak ? PropertyType.WEAKREFERENCE : PropertyType.REFERENCE);
	}

	public Binary createBinary(InputStream stream) throws RepositoryException {
		try {
			return new BinaryImpl(stream);
		} catch (IOException e) {
			throw new RepositoryException(e);
		}

	}

}